<template>
  <div class="map" id="map">
    <div class="tool-box">
      <span class="item" @click="addDraw('Point')">点选（点半径{{this.pointRadius}}）</span>
      <span class="item" @click="addDraw('Circle')">圈选</span>
      <span class="item" @click="addDraw('Polygon')">多边形框选</span>
    </div>
  </div>
</template>

<script>
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import {Sphere} from "ol"
import { transform } from "ol/proj"
import { Circle, Fill, Stroke, Style, Text } from "ol/style";
import {getDistance} from 'ol/sphere';
import { circular } from "ol/geom/Polygon"
import { Draw } from "ol/interaction";
import OSM from "ol/source/OSM";
import { Vector as VectorSource } from "ol/source";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { createStringXY } from "ol/coordinate"
import { FullScreen, defaults as defaultControls, MousePosition } from "ol/control";
import Point from "ol/geom/Point";
import LineString from "ol/geom/LineString";
import Polygon from "ol/geom/Polygon";
import CircleGeom from "ol/geom/Circle";
import Vector from "ol/layer/Vector"
import Feature from "ol/Feature";
import {tile as loadingstrategyTile } from 'ol/loadingstrategy';
import { createXYZ } from "ol/tilegrid";
import pointData from "./pointData"

// 聚合图标缓存，避免重复创建
var styleCache = [];
export default {
  name: "pgisMapSelect",
  data() {
    return {
      map: null,
      drawVector: null,
      pointRadius: 10,  // 点半径
      projection: "EPSG:3857",  // EPSG:4326 、EPSG:3857
    };
  },
  mounted() {
    this.init();
  },
  methods: {
    init() {
      //实例化地图
      this.map = new Map({
        layers: [
          new TileLayer({
            source: new OSM()
          })
        ],
        target: "map",
        view: new View({
          zoom: 12,
          minZoom: 5,
          maxZoom: 15,
          center: transform([113.05642461656782, 23.6758880181949], 'EPSG:4326', 'EPSG:3857'),
          projection: this.projection, // EPSG:4326
        }),
        controls: defaultControls({}).extend([
          new MousePosition({
            coordinateFormat: createStringXY(5), //保留5位小数
            projection: "EPSG:4326"
          }),
        ]),
      });
      this.curZoom = this.map.getView().getZoom().toFixed(0)
      // 监听地图分辨率变化事件
      this.map.getView().on("change:resolution", () =>{   
        this.resolutionChange = true             
        if (this.timer !== null) {
            clearTimeout(this.timer);
        }
        this.timer = setTimeout(() => {
            this.vectorSource.clear();
            this.curZoom = this.map.getView().getZoom().toFixed(0);
            this.resolutionChange = false
            this.addPointLayer(); // 地图分辨率变成完成后，重新请求渲染视野数据
        }, 35);
      })
      this.addPointLayer(); // 地图分辨率变成完成后，重新请求渲染视野数据
    },
    async addDraw(type) {
      // 绘制图层
      let {coordinate} = await this.getDrawFun(type)
      let params = {};
      let ary = []
      console.log(coordinate)
      switch (type) {
        case "Point":
          Object.assign(params,{
            coordinate: coordinate,
            radius: this.pointRadius
          })
          break;
        case "Circle":
          ary = coordinate.split(",")
          Object.assign(params,{
            coordinate: [ary[0],ary[1]],
            radius:ary[2]
          })
          this.getSelectInfo(params)
          break;
        case "Polygon":
          Object.assign(params,{
            coordinate:coordinate[0]
          })
          this.getSelectInfo(params)
          break;
      }     
    },
    // 此处需要把数据传递给后台，获取所需的数据 
    getSelectInfo(params) {
      console.log(JSON.stringify(params))
      // axios({
      //   method: "post",
      //   timeout: 1000,
      //   url: "http://192.168.30.10:8907/vector/tile",
      //   params,  // params，是和后台自己定义好的参数
      // }).then((rsp) => {
          let html =`参数：${JSON.stringify(params)};<br/>接口返回成功，此处应该返回，圈选的设备的详细信息。根据业务实际情况进行后续操作处理`
          this.$alert(html, '提示', {
            dangerouslyUseHTMLString: true,
            confirmButtonText: '确定',
          });
      // })
    },
    // 获取不同绘制对象的数据信息。
    getDrawFun(type) {
      this.drawVector = new VectorLayer({
        source: new VectorSource(),
        style: this.getStyle()
      });
      this.map.addLayer(this.drawVector)
      let draw =new Draw({
        source: this.drawVector.getSource(),
        type: type
      })
      this.map.addInteraction(draw);
      let promise = new Promise((reslove) =>{
        draw.on("drawend", (evt) =>{
          this.map.removeInteraction(draw);
          let geom = evt.feature.getGeometry();
          let coordinate = this.getCoordinateByFeature(geom)     
          reslove({
            coordinate
          })
        });
      })
      return promise
    },
    // 获取经纬度
    getCoordinateByFeature(geom) {
      let points = null;
      if (geom) {
          if (geom instanceof CircleGeom) {
            console.log(geom)
            // 1、在地图坐标系转为EPSG:3857下，geom.getRadius获取到的圆半径，单位为"米"
            // 2、在地图坐标系转为EPSG:4326下，geom.getRadius获取到的圆半径，单位为"度"
            let getRadius = geom.getRadius();
            points = geom.getCenter().join(",") + "," + getRadius;
            console.log(getRadius)
          } else if (geom instanceof LineString || geom instanceof Polygon || geom instanceof Point) {
            points = geom.getCoordinates();
          }
      }
      return points;
    },
    // 返回样式
    getStyle() {
      return new Style({
        fill: new Fill({
          color: "rgba(255, 255, 255, 0.2)"
        }),
        stroke: new Stroke({
          color: "#409EFF",
          width: 5
        }),
        image: new Circle({
          radius: 7,
          fill: new Fill({
            color: "#409EFF"
          })
        })
      })
    },
    // 地图点位数据加载
    addPointLayer() {
      this.vectorSource = new VectorSource({
          loader: (extent, resolution, projection) =>{
              //控制缩放结束前不发送请求
              if (this.resolutionChange)
              return false;
              // 此处loader自动请求后台数据，由于需要模拟数据，因为把请求注释。接口返回的实际，用pointData进行模拟
              // axios({
              //   method: "post",
              //   timeout: 1000,
              //   url: "http://192.168.30.10:8907/vector/tile",
              //   // params表示当前视野范围，把当前视野作为参数，传递给后台进行查询
              //   params: {
              //     minX: extent[0],
              //     minY: extent[1],
              //     maxX: extent[2],
              //     maxY: extent[3]
              //   },
              // }).then((rsp) => {
                // 接口返回成功以后，里面调用的方法
                  let z = Number(this.map.getView().getZoom().toFixed(0))
                  let rsp = pointData[z]; 
                  if (z == this.curZoom) {
                      let count = rsp.data.length
                      if(!count) {
                          return false
                      }
                      let features = new Array(count)
                      for (let i = 0; i < count; ++i) {
                          let coordinates = [Number(rsp.data[i].gpsX), Number(rsp.data[i].gpsY)]
                          if(this.projection == "EPSG:3857") {
                            coordinates = transform([Number(rsp.data[i].gpsX), Number(rsp.data[i].gpsY)], 'EPSG:4326', 'EPSG:3857')
                          }
                          let featureAttr = Object.assign({
                              geometry: new Point(coordinates),
                              data: rsp.data[i]
                          })
                          features[i] = new Feature(featureAttr);
                          features[i].setId(featureAttr.data.channel_ids)
                      }
                      this.vectorSource.addFeatures(features);
                  }
              // })
          },
          strategy: loadingstrategyTile(
              createXYZ({
                  tileSize: 512,
              })
          )
      });
      this.vectorTile = new Vector({                             
        // 此处预留按照图层名称进行渲染的入口，先写死图层名称为"layerName"，   
        style: feature => this.setClusterStyle(feature),   
        source: this.vectorSource
      })
      this.map.addLayer(this.vectorTile) 
    },
    // 设置聚合数据源样式
    setClusterStyle(feature) {
      let featureData = feature.get('data')
      if(JSON.stringify(featureData) == "{}"){
          return false
      }
      let count = featureData.count || 1          
      // 1-15层用count为1都显示聚合图标，16层及后面就显示正常图标（demo效果，暂未实现）。
      if (styleCache[count] == undefined) {
          styleCache[count] = new Style({
              image: new Circle({
                  radius: 16,
                  stroke: new Stroke({
                      color: '#fff',
                  }),
                  fill: new Fill({
                      color: 'rgba(97,134,236,0.9)'
                  })
              }),
              text: new Text({
                  font: '12px sans-serif',
                  text: ''+ count,
                  fill: new Fill({
                      color: '#fff',
                  }),
              })
          })
      }                               
      return styleCache[count] 
    },
  },
};
</script>

<style lang="less" scoped>
.map {
  height: 100%;
  position: relative;
  .tool-box {
    position: absolute;
    top: 10px;
    left: 60px;
    background: #fff;
    z-index: 100;
    padding: 15px;
    box-shadow: 3px 3px 20px #999;
    .item {
      font-size: 13px;
      color: #409EFF;
      margin: 0px 10px;
      border: 1px #409EFF solid;
      border-radius: 5px;
      padding: 5px;
      cursor: pointer;
    }
    .item:hover{
      background: #409EFF;
      color: #fff;
    }
  }
}
</style>